﻿using System;
using System.Windows;

namespace AdTech.Snap.Interop
{
    /// <summary>
    /// Win32 API Helper windows
    /// </summary>
    internal static class WindowInteropFactory
    {
        /// <summary>
        /// Gets a rectangle of the currently focused window.
        /// </summary>
        /// <returns>A <see cref="System.Windows.Rect"/> structure of the window boundaries.</returns>
        public static Rect GetFocusedWindowRect()
        {
            // Get focused window handle
            IntPtr hWnd = NativeMethods.GetForegroundWindow();

            // If the window is maximized, GetWindowRect has the odd behaviour of  returning
            // larger boundaries than expected, therefore we rely on the display size
            if (NativeMethods.IsZoomed(hWnd))
            {
                DisplayInfo displayInfo = MonitorInteropHelper.GetDisplayFromWindow(hWnd);
                return displayInfo.WorkingArea;
            }

            RECT rect = new RECT();
            NativeMethods.GetWindowRect(hWnd, ref rect);
            return rect;
        }

        /// <summary>
        /// Tries to set active focus on a given window.
        /// </summary>
        /// <param name="target">The handle of the window.</param>
        public static void ForceFocus(IntPtr target)
        {
            NativeMethods.SetForegroundWindow(target);
            NativeMethods.SetFocus(target);
        }

        /// <summary>
        /// Gets the current mouse cursor position on the screen.
        /// </summary>
        /// <returns>A <see cref="System.Windows.Point"/> structure of the position.</returns>
        public static Point GetCurrentPosition()
        {
            POINT point = new POINT();
            NativeMethods.GetCursorPos(out point);
            return point;
        }

        /// <summary>
        /// Converts screen coordinates relative to a client window.
        /// </summary>
        /// <param name="rectangle">A <see cref="System.Windows.Rect"/> structure containing information about the screen coordinates and size to convert.</param>
        /// <param name="client">A handle of the client window.</param>
        /// <returns>The converted rectangle.</returns>
        public static Rect ScreenToClient(Rect rectangle, IntPtr client)
        {
            POINT topLeft = rectangle.TopLeft;
            POINT bottomRight = rectangle.BottomRight;

            NativeMethods.ScreenToClient(client, ref topLeft);
            NativeMethods.ScreenToClient(client, ref bottomRight);

            return new Rect(topLeft, bottomRight);
        }

        /// <summary>
        /// Converts relative client window coordinates to the screen.
        /// </summary>
        /// <param name="rectangle">A <see cref="System.Windows.Rect"/> structure containing information about the client coordinates and size to convert.</param>
        /// <param name="client">A handle of the client window.</param>
        /// <returns>The converted rectangle.</returns>
        public static Rect ClientToScreen(Rect rectangle, IntPtr client)
        {
            POINT topLeft = rectangle.TopLeft;
            POINT bottomRight = rectangle.BottomRight;

            NativeMethods.ClientToScreen(client, ref topLeft);
            NativeMethods.ClientToScreen(client, ref bottomRight);

            return new Rect(topLeft, bottomRight);
        }
    }
}
